X-From_: ivan@solaris.kala.com  Tue Apr 14 03:18:09 1998
From: ivan@solaris.kala.com
Date: Tue, 14 Apr 1998 06:28:23 -0400
To: blades@spidweb.com
Subject: animation approaches that don't work - warnings for the unwary
Cc: ivan@solaris.kala.com
X-Sun-Charset: US-ASCII

I wanted to have an animation sequence at the beginning of a scenario,
giving the appearance of a storm on shipboard with lightning and thunder.

Easy, I thought. Use a special sequence on the start town, which
would contain one area of solid Pits (the black square) for the night,
and another with a slice of ship deck and adjacent water. For a lightning
flash, just move the party from the night to the ship and back, followed
by some boom sounds (sound 5 seems best) for the thunder. Stick in some
delays to space out the flashes, and slightly alter the ship deck in
different flashes (e.g. have a sailor figure move around, rocks go past in the
water, etc.) to give a strobe effect. Stick in a few dialogs to extend
the narrative and presto, a nice impressive opening.

Oops. BoE doen't do this sort of thing. I've spent quite a bit of time
finding approaches that don't work for effects of this kind, and this note
is to help others avoid repeating the waste.

First, getting into the sequence. In Advanced Town Details you can set a
special node which is called whenever the party enters the town. I wrote
a few specials of my anination, put the first special in the ADT slot,
and tried it out. No animation. Tried entering the town the usual way, and
the animation ran. Conclusion: BoE does not call the Town Enter special on
scenario startup. I call this a bug, but there you have it.

As a workaround, I set the startup location on the night pits and put the
animation start special in a ring surrounding the party. Changed the startup
text dialog so that it suggested that the ship was heaving enough to
stagger the party, and left the player to make the first move into the 
blackness and thus trigger my animation sequence. Had to create a new terrain
(with the Pit graphic but unblocked) so the party could step on the special, but
this workaround works. It might even be better for the player than simply
dumping him into the animation.

Now about the sequence itself. The move from night to ship and back does
give a nice flash. And it is easy to have crew and rocks move in consecutive
flashes as described. But continuous flash/bang/flash/bang... looks like
a disco gone berserk. A real storm has delays between flash and bang, and
the flashes come at random intervals. I needed a real-time delay special.
A 'Delay N milliseconds' sort of thing. There ain't one.

The first workaround idea was simply a counting delay loop. Set a SDF to a
large value, and loop decrementing it until zero. BoE would take some real
time to do the loop, and there's my delay. If I needed longer than the 255
size of a SDF, then a nested loop where the outer loop is decremented once
for each 255 times around the inner loop would do.

This loop would need to be executed quite a few time in my sequence, with
different values in the SDF being decremented. Aha! an obvious subroutine.
Have the mainline sequence stick the value corresponding to the desired
delay in a defined SDF, and subroutine-call the counting loop. This
would eliminate having to repeat the looping code literally in the
sequence at each point where I wanted a delay.

Guess what: despite the documentation always talking about 'calling'
a special, in reality BoE only _jumps_ to the special, and the 'return
address' is discarded. To do any complicated effects at all (not just
animations) BoE badly needs a true subroutine: "Call Special (and Return
Here When Finished)". Yes, this means that the engine would need to maintain
a stack, but that's no big deal. Got your ears on, Jeff?

So the sequences would have to have the delay loops in line longhand. Code
up the first couple of delays, and try it out.

And get a nice error message, "A Special may have at most 50 nodes". 
Mine had only 14 at that point, so what it means is that a special
may only _execute_ 50 nodes, including those it executes several times
as in my loop. 50 is much too few for a useful delay, much less an
entire sequence of them, so delay loops are out. 

This error message is actually a Good Thing, because it catches erroneous
specials that jump to themselves in an infinite loop. But 50 is a little
restrictive - 5000 might be better. But best of all would be a 'Reset
Node Counter' special node, which would let the writer tell BoE that
he knows that a particular special is intentionally longer than the
safety limit. Er - Jeff?

However, before I discovered the 50 limit, I had spent a little time
dealing with the variations in machine speeds. A particular delay loop
will run much more quickly on a fast machine. If I put in delay values
that give a nice storm on my machine, the result would be intolerably
boring on a slower machine and silent-movie jerky on a faster one. So
the actual counter values would have to depend on the player's machine speed.
How to calibrate this?

I wrote a dialog which ran before the storm started, telling the user
that the animations need calibration and for him to measure the time
(in seconds) between that message and the following one. By putting
a standard (uncalibrated) delay between the two messages, I could
measure how long in seconds (as reported by the user) corresponded to
what value in the counter. Then a little arithmetic would let me
scale all the counters to adjust for the host machine speed as calibrated.
Nifty.

Not quite. To begin with, while there is a Text Response node (which
accepts a string and compares it with a desired response), there is
no Numeric Response node which accepts a number and sticks the value
in a designated SDF. Shouldn't be too hard, because there are built-in
numeric dialogs throughout BoE (e.g. Give How Many when passing arrows
between members). Jeff?

So to get the value back from the user, I actually have to enter a binary tree
of dialogs: Did it take less than 32 seconds? Less than 16 seconds?
Less than 8 seconds? Less than 12 seconds? Less than 10 seconds? Aha, 9 seconds.
This is a pain for all concerned, but does get me a value. Now I have to scale
all my delay counter values to normalize them for the host machine.

Yes, arithmetic. BoE doesn't do arithmetic either. But it _is_ a Turing
machine (albeit with a non-infinite tape), so arithmetic _can_ be coded.
(For those unfamiliar with it, a Turing Machine is any computing process
which can perform all the computations which can be performed with two
bricks and a _very_ long roll of toilet paper. No, really.)

Addition and subtraction are relatively easy. Sit in a loop, decrementing
one SDF and incrementing another. When the decremented reaches zero, the
incremented holds the sum of the two. But scaling needs multiplication
and division. I had just begun considering the pain of doing multiplication
by repeated addition (and division by repeated subtraction) in the absence
of subroutines when I discovered the 50-node limit and abandoned the whole
delay-loop idea. Whew!

If Jeff ever does put an arithmetic capability in BoE, I suggest that
he define a limited number (255?) 32-bit registers rather than SDFs. Leave
the SDFs for the Boolean usage they are obviously intended for, and
define the arithmetic operations (and the necessary if-thens etc) on
the registers instead. And lest you think that all this is quite specialized
and would add little to scenarios, consider the following encounter:
you have been captured by brigands and for ransom they demand half your
gold, however much that is. Writing the special that does that is left
as an exercise (remember the 50-node limit, and the 30kGP wealth limit). Email
solutions (in the form of trivial scenarios) to me at ig@kala.com.

Meanwhile, back at the thunderstorm, I still needed a delay. The documentation
makes a big to-do about how it takes a long time to switch between towns.
So I thought that I could put in a delay by switching back and forth between
apparently identical (all black in my case) towns a few times. So we
need a stairway node. 

The first stairway out is no problem - Generic Stairway type 8 to a
scratch town. Of course, that's a one-way trip, whereas I wanted my sequence
to continue through the transfer. No problem - set a Town Enter special
on the scratch town, and it gets control as soon as the stairway finishes.
Put a Sound node on the enter, and try it out: Boom, as expected. Replace
the Sound with a Stairway back to my ship town. Have to keep the sequence
going through my return too, so added a Town Enter special on the Ship/Night
town, with a test sequence on an incremented SDF so I could tell
where in my sequence I was supposed to return to. This last was painful,
and could probably have been improved by having a large number of
duplicate Ship/Night towns and using Variable Town Entry and the incremented
SDF, at the expense of making the save file bigger. Try it out.

The sequence got to the scratch town OK, but the stairway back gives
an error "Cannot change level now". Seems you can't leave town during the
Town Enter special. This precludes not only my intended usage, but also
such things as the effect of a Variable Town Enter based on party
characteristics, i.e. enter this version of a town if the party is flying,
and this other one if entered by land. There seems no good reason for the
restriction in the likely implementation, so I call this a bug too.
Whatever.

So what else is there in BoE that takes a noticable amount of time? The
only thing I can think of is a sound. Whip out Inside Mac and read up
on snd resources, pull up ResEdit, and add a 99th sound to the BoE sound
file. The new sound is nothing but a 4-second delay. If it works, I'd
need a 1-, 2-, 8-, and 16-second delay too, but later. And unlike all
the town-switch kludges, this delay is true wall clock time and would not
need to be calibrated. Set up a test with a Play Sound of my new sound,
bracketed by a couple of booms. Try it.

Boom Boom. No delay in between. Must have screwed up the snd format. Re-read.
Looks OK. Try the new sound out in ResEdit, get a nice 'Playing' message 
that stays on the screen for 4 seconds. Now what? Get sneaky. Open the
sound file again, and rather than _add_ the new sound, _replace_ one of
the existing sounds. Change the sound numbers in my test case and try again.

Boom <pause> Boom. Bingo. BoE simply ignores sounds with numbers greater
than 98. I've got my delay, at the expense of eliminating an available
sound and requiring that my scenario be distributed with a substitute
sound file.

Now (before Jeff jumps in and explains why I shouldn't do this), the sound
file solution is a bad one. Yes, it does give me a delay. But users
who install my modified sound file will no doubt forget to put the
original one back when they finish my scenario, and will then try to
play other scenarios with the modified sound file. And wonder why the
game seems to stop for 32 seconds when a particular monster poops or
whatever and the scenario tries to use the standard sound I replaced.

The solution is to let users supply a custom sound file with each
scenario (augmenting rather then replacing the standard one), just as
they now can supply a custom graphics file. I can't imagine why Jeff
didn't do this in the original BoE - letting the authors define
custom noises seems so obviously in keeping with the rest of the
editor and game. _And_, I could get my delay. BoE1.1 maybe?

And by the way, I'd really like to see a 'Delay N Milliseconds' special
node.

RESPONSE FROM JEFF VOGEL:

I found this to be a fascinating article to read. You see, when I starting 
writing the editor, I had a very clear, straightforward, well defined idea
of what I wanted it to do, and what I wanted to be possible. Then I went out
and wrote the thing. As I wrote, some things went over the side (like 
black and white Exile III type graphics) and some things were added. 
However, I pretty much stuck with the basic ideas I started with.

Yet, had I worked on the editor for a million years, I don't think it ever would 
have occured to me that someone would have tried to do what you did. It
really, honestly amazes me that you made any progress at all.

Yes, the editor does have limitations. The lack of the ability to add more sounds,
for example. The sad truth is that the whole thing is very compilcated as it
is, both as a program and as a system for people to learn. At some point, I
felt I had to say "OK. This is enough. People can create a good adventure with
this, and, at the same time, it's simple enough for one person's brain to contain
it." And, at that point, I rested.

Given the editor's limitations, I'm amazed to see the tricks people work with it, 
and I can't wait to see your scenario (or what you finish of it).

By the way, yes, 50 nodes is too little. And no, the special node for town entry is
not supposed to be called when the scenario starts. However, there should be
a way to have a special encounter happen when the scenario starts. As for queueing 
special encoutners and having subroutines, I dunno. It seems like a good idea, but
the simple way its set up had an appeal as being something a normal person would
have a better chance of learning.

- Jeff Vogel

